package javathread;

public class ThreadSafe {
    public static void main(String[] args) {
        window2 w=new window2();
        Thread t1=new Thread(w);
        Thread t2=new Thread(w);
        Thread t3=new Thread(w);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }

}

/**
 * 卖票的过程中出现了重票和错票问题，这就是线程的安全问题
 * 问题出现的原因：某个线程操作车票尚未完成，其他线程参与进来也来操作车票
 * 如何解决：当线程a操作共享数据的时候，其他线程不能参与进来，
 *        直到a操作结束后其他线程才可以参与进来即使a出现了阻塞也不能被改变
 *在java中通过同步机制来解决线程安全问题
 *       方式1：同步代码块 synchronized(同步监视器){
 *              需要被同步的代码
 *          }
 *              1就是操作共享数据的代码
 *              2共享数据是多个线程共同操作的变量
 *              3同步监视器俗称锁，任何一个类的对象都可以充当锁
 *              4.要求多个线程必须共用同一把锁 ，Object obj=new Object();obj必须是一个
 *              5.同步的方式解决了线程的安全问题，但是操作同步代码时只能有一个线程参与其他线程等待，相当于是一个单线程过程，效率低
 *              6.实现runable接口的线程可以用this作为锁
 *
 *       方式2：同步方法,如果操作共享数据的代码在一个方法中，我们可以将此方法声明为同步方法
 *       如果使用继承thread方法的线程需要用static修饰，同步监视器是XXX.class
 *       如果是实现runable，同步监视器是this
 *
 */
class window1 implements Runnable{
 private int ticket=100;
 Object obj=new Object();
    @Override
    public void run() {

        while(true){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (obj) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }
        }
    }
}

class window2 implements Runnable{
    private int ticket=100;
    Object obj=new Object();
    @Override
    public void run() {

        for (int i = 0; i <=100 ; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.show();
        }
    }
    public synchronized void show(){

            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + ":" + ticket);
                ticket--;
        }
    }
}
